package viz.model.flare.decoders
{
	import flare.vis.data.Data;
	import flare.vis.data.EdgeSprite;
	import flare.vis.data.NodeSprite;
	import flare.vis.data.Tree;
	
	import viz.model.IDecodeable;
	import viz.model.flare.data.ActionItem;
	import viz.model.flare.data.StateItem;
	import viz.model.flare.data.StateMap;


	public class StateMap2Flare implements IDecodeable
	{
		private var map:Object;
		private var actions:Array;
		private var o:Object;
		
		public function StateMap2Flare( o:Object ):void{
			this.o = o;
		}
		
		public function decode( ):Object{
			var d:Object;
			if( !o is StateMap) throw new Error("StateMap expected");
			d = buildData( o as StateMap );
			cleanup();
			return d;
		}
		
		private function cleanup():void{
			//map = null
		}
		
		public function buildData(tuples:StateMap):Data
		{
			var fdata:Data = new Data();
			var tree:Tree = new Tree();
			map ={};
			
			tree.root = fdata.addNode({name:"root", size:0});
			map.root = tree.root;
			
			var t:StateItem, u:NodeSprite, v:NodeSprite;
			var p:String, pp:String, i:uint;
			
			// build data set and tree edges
			//tuples.sortOn("fullPath");
			for each (t in tuples) {
				addTuple(t, fdata, tree)
			}
			
			actions = createActions(tuples, fdata);
			
			
			
			
			for each (u in tree.nodes) {
				u.sortEdgesBy(NodeSprite.CHILD_LINKS, "target.data.order");
			}
			
			fdata.tree = tree;
			return fdata;
		}
		
		private function createActions(tuples:StateMap, fdata:Data):Array{
			// create graph links
			var t:StateItem,
				a:Array = [],
				sourceNode:NodeSprite,
				targetNode:NodeSprite,
				action:ActionItem,
				actionEdge:EdgeSprite;
			
			for each (t in tuples) {
				sourceNode = map[t.fullPath];
				for each ( action in t.actions) {
					targetNode = map[action.target.fullPath];
					if (targetNode){
						actionEdge = fdata.addEdgeFor(sourceNode, targetNode, true);
						actionEdge.data = action;
						a.push( action );
					} 
					else trace ("Missing node: "+action.name);
				}
			}
			return a;
		}
		
		private function addTuple(t:StateItem, fdata:Data, tree:Tree):void{
			var u:NodeSprite;
			var path:Array, p:String;
			
			p = addGroupToTree(fdata, tree, t.pkgArray);
				
			u = fdata.addNode(t);
			tree.addChild(map[p], u);
			map[t.fullPath] = u;
		}
		
		private function addGroupToTree(fdata:Data, tree:Tree, path:Array):String{
			var u:NodeSprite;
			var p:String, pp:String, i:uint;
			for (i=0, p=""; i<path.length; ++i) {
					pp = p;
					p += (i?".":"") + path[i];
					if (!map[p]) {
						u = fdata.addNode({name:p, size:0});
						tree.addChild(map[pp], u);
						map[p] = u;
					}
				}
				return p
			}
			
	}
	
	
}